package com.isoft.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.isoft.mapper.TableMapper;
import com.isoft.pojo.dto.FieldDTO;
import com.isoft.pojo.dto.PageQueryTableDTO;
import com.isoft.pojo.dto.TableCreateDTO;
import com.isoft.pojo.entity.Field;
import com.isoft.pojo.entity.Table;
import com.isoft.pojo.vo.*;
import com.isoft.result.PageResult;
import com.isoft.result.Result;
import com.isoft.service.TableService;
import io.micrometer.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
@Transactional
public class TableServiceImpl implements TableService {

    @Autowired
    private TableMapper tableMapper;

    /**
     * 获取表列表
     * @param pageQueryTableDTO
     * @return
     */
    @Override
    public Result<PageResult<Table1VO>> getTableList(PageQueryTableDTO pageQueryTableDTO) {
        // 分页处理
        PageHelper.startPage(pageQueryTableDTO.getPage(), pageQueryTableDTO.getSize());

        // 1. 查询表基本信息
        List<Table1VO> tableList = tableMapper.getTableList(pageQueryTableDTO);
        PageInfo<Table1VO> pageInfo = new PageInfo<>(tableList);

        // 2. 获取表ID集合
        List<String> tableIds = tableList.stream()
                .map(Table1VO::getId)
                .collect(Collectors.toList());

        // 3. 批量查询字段信息
        if (!CollectionUtils.isEmpty(tableIds)) {
            List<FieldVO> fields = tableMapper.getFieldsByTableIds(tableIds);

            // 4. 按表ID分组字段
            Map<String, List<FieldVO>> fieldMap = fields.stream()
                    .collect(Collectors.groupingBy(FieldVO::getTableId));

            // 5. 设置字段到表对象
            tableList.forEach(table ->
                    table.setFields(fieldMap.get(table.getId()))
            );
        }

        // 6. 构建分页结果
        PageResult<Table1VO> result = new PageResult<>(pageInfo, tableList);
        return Result.success(result);
    }

    /**
     * 获取表详情
     * @param id
     * @return
     */
    @Override
    public Result<TableVO> getTableByIds(String id) {
        // 1. 查询表信息
        List<TableVO> tableVOList = (List<TableVO>) tableMapper.getTableByIds(Collections.singletonList(id));
        TableVO tableVO = tableVOList.isEmpty() ? null : tableVOList.get(0);


        if (tableVO != null) {
            // 2. 查询字段信息
            List<FieldVO> fields = tableMapper.getFieldsByTableIds(Arrays.asList(id));

            // 3. 设置字段信息
            tableVO.setFields(fields);
        }
        log.info("查询表详情：{}", tableVO);
        return Result.success(tableVO);
    }

    /**
     * 核心创建表逻辑（跳过检查）
     * @param dto
     * @return
     */
    private boolean createTableInternal(TableCreateDTO dto) {
        // 1. 创建表基本信息
        Table tableEntity = new Table();
        tableEntity.setSysId(dto.getSystemId());
        tableEntity.setTableName(dto.getTableName());
        tableEntity.setCode(dto.getTableCode());

        tableMapper.insertSysTable(tableEntity);

        Integer tableId = tableEntity.getId();

        // 2. 构建建表 SQL 并执行
        StringBuilder sqlBuilder = new StringBuilder();
        sqlBuilder.append("CREATE TABLE ").append(dto.getTableCode()).append(" (");

        List<String> columnDefinitions = new ArrayList<>();
        List<String> primaryKeyColumns = new ArrayList<>();

        for (TableCreateDTO.FieldDTO field : dto.getFields()) {
            StringBuilder columnDef = new StringBuilder();
            columnDef.append(field.getName()).append(" ").append(field.getType());

            if ("高".equals(field.getSecurityLevel())) {
                columnDef.append(" ENCRYPTED");
            }

            if (Boolean.TRUE.equals(field.getIsPrimaryKey())) {
                columnDef.append(" PRIMARY KEY");
                primaryKeyColumns.add(field.getName());
            }

            columnDefinitions.add(columnDef.toString());
        }

        sqlBuilder.append(String.join(", ", columnDefinitions));

        if (!primaryKeyColumns.isEmpty()) {
            sqlBuilder.append(", PRIMARY KEY (");
            sqlBuilder.append(String.join(", ", primaryKeyColumns));
            sqlBuilder.append(")");
        }

        sqlBuilder.append(");");

        log.info("生成的建表SQL: {}", sqlBuilder.toString());

        // 执行建表 SQL（需替换为实际的执行方式）
        // jdbcTemplate.execute(sqlBuilder.toString());

        // 3. 插入字段信息到 sys_table_field
        List<Field> fields = dto.getFields().stream()
                .map(fieldDTO -> {
                    Field field = new Field();
                    field.setTableId(tableId);
                    field.setFieldName(fieldDTO.getName());
                    field.setFieldType(fieldDTO.getType());
                    field.setClassification(fieldDTO.getClassification());
                    field.setDescription(fieldDTO.getDescription());
                    field.setSecurityLevel(convertSecurityLevel(fieldDTO.getSecurityLevel()));
                    field.setIsPrimaryKey(fieldDTO.getIsPrimaryKey() != null && fieldDTO.getIsPrimaryKey()); // 设置主键标识
                    return field;
                })
                .collect(Collectors.toList());

        tableMapper.batchInsertFields(fields);

        return true;
    }

    /**
     * 新增表（带检查）
     * @param dto
     * @return
     */
    @Override
    public boolean createTable(TableCreateDTO dto) {
        // 检查表名是否重复
        String tableName = dto.getTableName();
        Table existingTable = tableMapper.findTableByTableName(tableName);
        if (existingTable != null) {
            throw new RuntimeException("表名已存在: " + tableName);
        }

        // 检查表编码是否重复
        String tableCode = dto.getTableCode();
        Table existingTableCode = tableMapper.findTablecode(tableCode);
        if (existingTableCode != null) {
            throw new RuntimeException("表编码已存在: " + tableCode);
        }

        return createTableInternal(dto);
    }

    /**
     * 导入SQL文件解析表结构
     * @param file
     * @param systemId
     * @param override
     * @return
     */
    @Override
    public ImportResultVO importSql(MultipartFile file, String systemId, boolean override) {
        ImportResultVO result = new ImportResultVO();
        List<TableImportResult> tableResults = new ArrayList<>();

        try {
            log.info("开始导入SQL文件: {}, systemId: {}, override: {}",
                    file.getOriginalFilename(), systemId, override);

            // 读取SQL文件内容
            String sqlContent = new String(file.getBytes(), StandardCharsets.UTF_8);
            log.debug("SQL文件内容:\n{}", sqlContent);

            // 解析SQL
            List<com.isoft.util.SqlParserUtil.SqlTable> parsedTables = com.isoft.util.SqlParserUtil.parseSql(sqlContent);
            log.info("解析到 {} 个表", parsedTables.size());

            // 解析到的表数量为0，立即抛出异常
            if (parsedTables == null || parsedTables.isEmpty()) {
                throw new RuntimeException("SQL解析失败，未发现有效表结构");
            }
            for (com.isoft.util.SqlParserUtil.SqlTable table : parsedTables) {
                log.info("处理表: {}", table.getTableName());
                TableImportResult tableResult = new TableImportResult();
                tableResult.setTableName(table.getTableName());

                try {
                    // 1. 检查系统是否存在
                    if (!tableMapper.systemExists(Integer.parseInt(systemId))) {
                        throw new RuntimeException("系统不存在");
                    }

                    // 2. 检查表是否已存在
                    Table existingTable = tableMapper.findTableByNameAndSystem(table.getTableName(), systemId);
                    if (existingTable != null) {
                        if (override) {
                            // 覆盖模式：删除旧表
                            log.info("覆盖模式: 删除旧表 {}", table.getTableName());
                            tableMapper.deleteFieldsByTableId(existingTable.getId());
                            tableMapper.deleteTableById(existingTable.getId());

                            // 验证表是否已删除
                            Table stillExists = tableMapper.findTableByNameAndSystem(table.getTableName(), systemId);
                            if (stillExists != null) {
                                throw new RuntimeException("删除旧表失败，表仍然存在");
                            }
                        } else {
                            throw new RuntimeException("表已存在且未启用覆盖模式");
                        }
                    }

                    // 3. 创建新表DTO
                    TableCreateDTO dto = new TableCreateDTO();
                    dto.setSystemId(Integer.valueOf(systemId));
                    dto.setTableName(table.getTableName());
                    dto.setTableCode(generateTableCode(table.getTableName()));

                    // 4. 转换字段
                    List<TableCreateDTO.FieldDTO> fields = new ArrayList<>();
                    for (com.isoft.util.SqlParserUtil.SqlColumn column : table.getColumns()) {
                        FieldDTO fieldDTO = new FieldDTO();
                        fieldDTO.setName(column.getName());

                        // 验证字段类型
                        String fieldType = column.getType();
                        if (fieldType == null || fieldType.trim().isEmpty()) {
                            fieldType = "UNKNOWN";
                            log.warn("字段 {} 类型为空，使用默认值 UNKNOWN", column.getName());
                        }
                        fieldDTO.setType(fieldType);

                        fieldDTO.setClassification("未分类");
                        fieldDTO.setSecurityLevel("低");
                        fieldDTO.setDescription(StringUtils.isBlank(column.getComment()) ?
                                "无描述" : column.getComment());
                        fields.add(fieldDTO);
                    }
                    dto.setFields(fields);

                    // 5. 保存到数据库
                    log.info("保存表: {}", table.getTableName());
                    boolean success;

                    if (override) {
                        // 覆盖模式下直接调用内部创建方法（跳过检查）
                        success = createTableInternal(dto);
                    } else {
                        // 非覆盖模式调用标准创建方法（带检查）
                        success = createTable(dto);
                    }

                    if (success) {
                        tableResult.setStatus("SUCCESS");
                        tableResult.setMessage("成功导入");
                        result.setSuccessCount(result.getSuccessCount() + 1);
                    } else {
                        throw new RuntimeException("创建表失败");
                    }
                } catch (Exception e) {
                    log.error("导入表失败: {}", table.getTableName(), e);
                    tableResult.setStatus("FAILED");
                    tableResult.setMessage(e.getMessage());
                    result.setFailedCount(result.getFailedCount() + 1);
                }
                tableResults.add(tableResult);
            }

            result.setTables(tableResults);
            return result;

        } catch (Exception e) {
            log.error("解析SQL文件失败", e);
            throw new RuntimeException("解析SQL文件失败: " + e.getMessage());
        }
    }



    // 生成表编码（表名大写+下划线）
    private String generateTableCode(String tableName) {
        return tableName.toUpperCase().replaceAll("\\s+", "_");
    }

    /**
     * 将安全等级字符串转换为Short类型
     * @param level
     * @return
     */
    private Short convertSecurityLevel(String level) {
        switch (level) {
            case "低": return 1;
            case "中": return 2;
            case "高": return 3;
            default: return 1;
        }
    }
}